use crate::kzz::kzzs_craw::update_kzz_list_all_from_eastmoney;
use cron::Schedule;
use log::debug;
use log::error;
use log::info;
use once_cell::sync::Lazy;
use std::fmt;
use std::str::FromStr;

// Create a vector of jobs
pub(crate) static JOBS: Lazy<Vec<Job>> = Lazy::new(|| {
    vec![
        Job::new(
            "update_kzz_list_all_from_eastmoney",
            Schedule::from_str("* 31 15 * * Mon,Tue,Wed,Thu,Fri").unwrap(),
            Box::new(|| {
                tokio::spawn(async move {
                    // job 1 implementation
                    // run job here
                    let rs = update_kzz_list_all_from_eastmoney().await;
                    match rs {
                        Ok(_) => {
                            info!("Job(update_kzz_list_all_from_eastmoney) completed successfully")
                        }
                        Err(e) => error!(
                            "Job(update_kzz_list_all_from_eastmoney) failed with error: {}",
                            e
                        ),
                    }
                })
            }),
        ),
        Job::new(
            "generate_craw_tasks_from_eastmoney",
            Schedule::from_str("* 31 16 * * Mon,Tue,Wed,Thu,Fri,Sat").unwrap(), // Every 10 minutes
            Box::new(|| {
                tokio::spawn(async move {
                    // job 2 implementation
                    // run job here
                    debug!("run generate_craw_tasks_from_eastmoney job at 16:31");
                })
            }),
        ), 
        Job::new(
            "job10minutes",
            Schedule::from_str("* 10 * * * *").unwrap(), // Every 10 minutes
            Box::new(|| {
                tokio::spawn(async move {
                    // job 2 implementation
                    // run job here
                    debug!("run job10minutes for every 10  minutes");
                })
            }),
        ),
        Job::new(
            "job5minutes",
            Schedule::from_str("5 * * * * *").unwrap(),
            Box::new(|| {
                tokio::spawn(async move {
                    // job 2 implementation
                    // run job here
                    debug!("run job5minutes for every 5  minutes");
                })
            }),
        ),
        // Add more jobs as needed
    ]
});

// Define a struct to hold job information
#[derive(Debug)]
pub(crate) struct Job {
    pub schedule: Schedule,
    pub job_name: String, // New field to hold the name of the job function

    pub fn_wrapper: JobFunctionWrapper,
}
// Define a newtype wrapper around the trait object
pub struct JobFunctionWrapper {
    pub job_function: Box<dyn Fn() -> tokio::task::JoinHandle<()> + Send + Sync>,
}

// Implement Debug for the newtype
impl fmt::Debug for JobFunctionWrapper {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "JobFunctionWrapper")
    }
}

impl Job {
    fn new(
        job_name: &str,
        schedule: Schedule,
        job_function: impl Fn() -> tokio::task::JoinHandle<()> + 'static + Send + Sync,
    ) -> Self {
        Job {
            schedule,
            job_name: job_name.to_string(),
            fn_wrapper: JobFunctionWrapper {
                job_function: Box::new(job_function),
            },
        }
    }
}
